<!-- Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 -->
<!-- 
* @desc:树形菜单
* @fileName:Tree.vue
* @author:chenxiaofeng@yzbdl.ac.cn
* @date:2022-4-8
!-->
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import {
  Search,
  CircleCheckFilled,
  Plus,
  EditPen,
  CircleCloseFilled,
  Delete,
} from "@element-plus/icons-vue";
import type Node from "element-plus/es/components/tree/src/model/node";
import { ElMessage, ElTree } from "element-plus";
import { TreeNodeData } from "element-plus/lib/components/tree/src/tree.type";
import "element-plus/theme-chalk/el-tree.css";

const props = defineProps({
  // 树数据
  dataSource: {
    type: Array as any,
    default: [],
  },
  // 回传选中的节点ID
  getTableList: Function as any,
  // 树加载动画
  isTreeLoading: {
    type: Boolean,
    default: false,
  },
  //添加节点方法实现
  addNode: Function,
  //删除节点方法实现
  delNode: Function,
  //修改节点方法实现
  editNode: Function,
});
// 定义树形菜单数据类型
interface Tree {
  id: number;
  groupName: string;
  children?: Tree[];
}

// 定义搜索名称
const searchValue = ref("");
const treeRef = ref<InstanceType<typeof ElTree>>();
// 添加节点输入框值
let addOrEdit = ref("");
// 添加框隐藏显示标识
let isAdd = ref(false);
// 子节点ID存放变量-供添加节点使用
let childNodeId = ref(0);
// 子节点内容变量
let childNodeValue = ref("");
// 新增子节点，存放父节点信息
let childPid = ref("");
// 子节点ID存放变量-供修改节点使用
let editChildNOdeId = ref(0);
// 编辑标识
let isEdit = ref(true);
// 编辑节点值存放变量
let editChildValue = ref("");
// 点击树每一行存当前ID
let iconShowId = ref(0);
// 定义编辑时 是否显示操作按钮
let isShowOprationIcon = ref(true);

/**
 * 监听输入值的改变
 */
watch(searchValue, (val) => {
  treeRef.value!.filter(val);
});

/**
 * 通过过滤的值筛选树形菜单
 * @param value 关键词
 * @param data 树数据
 * @reture 已过滤数据
 */
const filterNode = (value: string, data: TreeNodeData) => {
  if (!value) return true;
  return data.groupName.includes(value);
};

/**
 * 根节点内容添加
 * @reture viod
 */
const addRootNode = () => {
  if (addOrEdit.value === "") {
    ElMessage({
      message: "节点内容不能为空",
      type: "info",
    });
  } else {
    isAdd.value = false;
    const item = {
      groupName: addOrEdit.value,
      pid: "",
    };
    props.addNode?.(item);
  }
};

/**
 * 关闭新增节点输入框
 * @reture viod
 */
const closeInput = () => {
  addOrEdit.value = "";
  isAdd.value = false;
};

/**
 * 子节点内容添加
 * @reture viod
 */
const addChidrenNode = () => {
  if (childNodeValue.value === "") {
    ElMessage.error("节点内容不能为空");
  } else {
    const item = {
      groupName: childNodeValue.value,
      pid: childPid.value,
    };
    props.addNode?.(item);
  }
  childNodeId.value = 0;
};

const closeChildrenInput = () => {
  childNodeValue.value = "";
  childNodeId.value = 0;
};

/**
 * 添加方法
 * @param data 当前行数据
 * @reture viod
 */
const append = (data: Tree) => {
  childPid.value = data.id.toString();
  childNodeValue.value = getDefaultFolderName(data.children);
  childNodeId.value = data.id;
};

/**
 * 根据当前节点获取新节点默认名称
 */
const getDefaultFolderName = (treeList?: Tree[]): string => {
  const DEFAULT_NAME = "分组";
  if (treeList) {
    let numberList = treeList.map((item) => {
      if (item.groupName.indexOf(DEFAULT_NAME) > -1) {
        let arr = item.groupName.split(DEFAULT_NAME);
        if (arr.length == 2) {
          if (arr[1] == "") {
            return 0;
          }
          if (!isNaN(Number(arr[1])) && Number(arr[1]) + "" == arr[1]) {
            return Number(arr[1]);
          }
        }
      }
      return -1;
    });
    if (numberList) {
      let max = Math.max(...numberList);
      if (max > -1) {
        return `${DEFAULT_NAME}${max + 1}`;
      }
    }
  }
  return DEFAULT_NAME;
};

/**
 * 编辑方法
 * @param node 当前节点信息
 * @param data 当前行数据
 * @reture viod
 */
const edit = (node: Node, data: Tree) => {
  editChildNOdeId.value = data.id;
  isShowOprationIcon.value = false;
  isEdit.value = true;
  editChildValue.value = data.groupName.split("(")[0];
};

/**
 * 移除方法
 * @param data 当前行数据
 * @reture viod
 */
const remove = (data: any) => {
  props.delNode?.(data.id);
};

/**
 * 修改节点方法
 * @reture viod
 */
const editNodeSubmit = () => {
  if (editChildValue.value === "") {
    ElMessage.info("节点内容不能为空!");
    return;
  }
  let item = {
    groupName: editChildValue.value,
    id: editChildNOdeId.value,
  };
  props.editNode?.(item);
  isShowOprationIcon.value = true;
  editChildNOdeId.value = 0;
  isEdit.value = true;
  editChildValue.value = "";
};

const closeNodeInput = () => {
  isShowOprationIcon.value = true;
  editChildValue.value = "";
  editChildNOdeId.value = 0;
  isEdit.value = true;
};

const defaultProps = {
  children: "children",
  label: "groupName",
};

/**
 * 节点点击方法
 * @param data 节点数据
 * @reture viod
 */
const nodeClick = (data: Tree) => {
  iconShowId.value = data.id;
  props.getTableList(data.id);
};

/**
 * 根据等级截取显示长度
 * @param data 节点数据
 * @reture viod
 */
const ellicpis = (data: any) => {
  if (!data.groupName) return "";
  if (data.level === 1 && data.groupName.length >= 13) {
    return data.groupName.slice(0, 13) + "...";
  } else if (data.level === 2 && data.groupName.length >= 12) {
    return data.groupName.slice(0, 12) + "...";
  }
  if (data.level === 3 && data.groupName.length >= 10) {
    return data.groupName.slice(0, 10) + "...";
  }
  if (data.level === 4 && data.groupName.length >= 9) {
    return data.groupName.slice(0, 9) + "...";
  }
  if (data.level === 5 && data.groupName.length >= 8) {
    return data.groupName.slice(0, 8) + "...";
  }
  return data.groupName;
};

/**
 * 顶部新增按钮点击事件
 */
const onRootAddButtonClick = () => {
  isAdd.value = true;
  addOrEdit.value = getDefaultFolderName(
    props.dataSource?.length > 0 && props.dataSource[0].children
  );
};

onMounted(() => {
  setTimeout(() => {
    if (props.dataSource.length < 1) return;
    treeRef.value?.setCurrentKey(props.dataSource[0].id);
    iconShowId.value = props.dataSource[0].id;
  }, 100);
});
</script>

<template>
  <!-- 操作区域 -->
  <div class="opration">
    <el-input
      class="search-input"
      v-model="searchValue"
      placeholder="请输入分组名称"
    ></el-input>
    <el-button class="add-btn" @click.stop="onRootAddButtonClick()" :icon="Plus"
      >新增</el-button
    >
  </div>
  <!-- 新增、编辑 -->
  <div class="flex add-root-node" v-if="isAdd">
    <img class="folder" src="../../assets/img/task-resource/folder.png" />
    <el-input
      v-model="addOrEdit"
      placeholder="请输入根节点"
      maxlength="64"
    ></el-input>
    <span @click="addRootNode" class="add-submit"
      ><el-icon class="sub"><circle-check-filled /></el-icon
    ></span>
    <span @click="closeInput" class="add-submit"
      ><el-icon class="close"><CircleCloseFilled /></el-icon
    ></span>
  </div>
  <!-- 树形页面 -->
  <div class="the-tree">
    <el-tree
      ref="treeRef"
      v-loading="props.isTreeLoading"
      :data="props.dataSource"
      :props="defaultProps"
      node-key="id"
      :highlight-current="true"
      default-expand-all
      :filter-node-method="filterNode"
      :expand-on-click-node="false"
      v-if="props.dataSource.length > 0"
    >
      <template #default="{ node, data }">
        <!-- 树形菜单自定义dom -->
        <span
          class="custom-tree-node"
          @click="nodeClick(data)"
          :class="iconShowId === data.id ? 'actived' : ''"
        >
          <!-- 正常显示节点内容 -->
          <span class="word" v-if="data.id !== editChildNOdeId && isEdit"
            ><img
              class="folder"
              src="../../assets/img/task-resource/folder.png"
            />
            <lanius-tooltip :content="node.label">
              {{ ellicpis(data) }}</lanius-tooltip
            ></span
          >
          <!-- 点击编辑后显示输入框 -->
          <span v-if="data.id === editChildNOdeId && isEdit">
            <img
              class="folder"
              src="../../assets/img/task-resource/folder.png"
            />
            <el-input
              class="edit-root-name"
              maxlength="64"
              v-model="editChildValue"
            ></el-input>
            <span class="add-submit" @click="editNodeSubmit"
              ><el-icon class="sub"><circle-check-filled /></el-icon
            ></span>
            <span @click="closeNodeInput" class="add-submit"
              ><el-icon class="close"><CircleCloseFilled /></el-icon
            ></span>
          </span>
          <span
            class="custom-tree-opration"
            v-if="data.id !== '-1' && isShowOprationIcon"
          >
            <!-- 添加节点 -->
            <lanius-tooltip content="新增">
              <a
                class="opration-icon plus"
                v-if="data.level < 6"
                @click.stop="append(data)"
              >
                <el-icon class="custom-icon-plus"><plus /></el-icon> </a
            ></lanius-tooltip>

            <!-- 编辑节点 -->
            <lanius-tooltip content="编辑">
              <a class="opration-icon edit-pen" @click.stop="edit(node, data)">
                <el-icon class="custom-icon-edit"><EditPen /></el-icon>
              </a>
            </lanius-tooltip>

            <!-- 删除节点 -->
            <lanius-pop-confirm
              title="删除提示"
              :content="'确定删除分组?'"
              @confirm="remove(data)"
            >
              <div style="display: inline">
                <span class="opration-icon delete">
                  <lanius-tooltip content="删除">
                    <el-icon class="custom-icon-delete"><delete /></el-icon>
                  </lanius-tooltip>
                </span>
              </div>
            </lanius-pop-confirm>
          </span>
        </span>
        <span @click="nodeClick(data)" class="custom-tree-number"
          >资源:{{ data.count }}</span
        >
        <!-- 子节点添加dom -->
        <div class="no-flex" v-if="data.id === childNodeId">
          <img class="folder" src="../../assets/img/task-resource/folder.png" />
          <el-input
            class="edit-root-name"
            maxlength="64"
            v-model="childNodeValue"
          ></el-input>
          <span @click="addChidrenNode"
            ><el-icon class="sub"><circle-check-filled /></el-icon
          ></span>
          <span @click="closeChildrenInput" class="add-submit"
            ><el-icon class="close"><CircleCloseFilled /></el-icon
          ></span>
        </div>
      </template>
    </el-tree>
    <!-- 数据为空显示 -->
    <template v-if="props.dataSource.length === 0" slot="empty">
      <el-empty description="暂无数据" />
    </template>
  </div>
</template>

<sytle lang="scss">
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
  background-color: #f5f7fa !important;
}
</sytle>

<style scoped lang="scss">
.custom-tree-number {
  flex-basis: 100%;
  padding-left: 50px;
  position: relative;
  font-size: 12px;
  top: -5px;
  line-height: 25px;
}
.opration-icon {
  background-color: #f1f1f1;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  text-align: center;
  line-height: 20px;
  margin-right: 5px;
  display: inline-block;
  .el-icon {
    color: #6a6a6a;
    font-size: 12px;
  }
}
.delete {
  margin-right: 0;
}
.actived {
  .custom-tree-opration {
    display: inline-block !important;
  }
}
.custom-tree-node {
  min-width: 200px;
  .plus {
    &:hover {
      background-color: #5473e6 !important;
      .el-icon {
        color: #fff;
      }
    }
  }
  .edit-pen {
    &:hover {
      background-color: #f5b900 !important;
      .el-icon {
        color: #fff;
      }
    }
  }
  .delete {
    &:hover {
      background-color: #e85a5a !important;
      .el-icon {
        color: #fff;
      }
    }
  }
  .custom-tree-opration {
    display: none;
  }
}
.edit-root-name {
  width: 120px;
}
.sub {
  color: #55d66b;
  margin-left: 5px;
}
.close {
  color: red;
  margin-left: 3px;
}
.add-root-node {
  margin-top: 10px;
  height: 30px;
  line-height: 30px;
  img {
    position: relative;
    top: 5px;
  }
  :deep(.el-input__inner) {
    height: 30px;
    line-height: 30px;
  }
}
:deep(.el-tree-node__content) {
  height: auto;
  flex-wrap: wrap;
  line-height: 30px;
}
.no-flex {
  flex-direction: column;
  width: 65%;
  img {
    margin-left: 42px;
  }
  span {
    margin-left: 5px;
  }
}
.flex {
  display: flex;
  .add-submit {
    cursor: pointer;
  }
}
.opration {
  display: flex;
  .el-input {
    :deep(.el-input__inner) {
      height: 30px;
      line-height: 30px;
      border-radius: 0;
      border-color: #ccc;
    }
    :deep(.el-input__suffix) {
      right: 18px;
      color: #000;
    }
  }
  .icon {
    width: 12px;
    height: 12px;
    margin-right: 10px;
  }
  .search-input {
    flex: 1;
  }
  .el-button {
    width: 70px;
    height: 30px;
    border-radius: 0;
    color: #000;
    border-color: #ccc;
  }
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  color: rgba($color: #000000, $alpha: 0.5);
  .last.icon {
    margin-right: 0;
  }
}

.the-tree {
  margin-top: 15px;
  height: calc(100vh - 220px);
  overflow: auto;
}

.folder {
  width: 20px;
  height: 16px;
  margin-right: 5px;
  position: relative;
  top: 2px;
}

.add-btn {
  margin-left: 10px;
  width: 70px;
  height: 30px;
  border-radius: 0;
  background-color: #f2f2f6;
  color: #000;
  border: 0;
  &:hover {
    background-color: #5473e6;
    color: #fff;
  }
}

.search-input {
  :deep(.el-input__wrapper) {
    height: 30px;
    border-radius: 0;
    background-color: #f2f2f6 !important;
    box-shadow: unset !important;
  }
}
</style>
